#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using FibMatrix.DS;
using UnityEditor;
using UnityEngine;

namespace FibMatrix
{
    /// <summary>
    /// AssetDatabase资源模式的实现
    /// </summary>
    [FM_Mono.IgnoreGen]
    public class AssetDBResourceFacadeImpl : AbstractResourceFacadeImpl
    {
        private ObjectPool2<ResourcePipelineContext> _contextPool = new ObjectPool2<ResourcePipelineContext>(-1, () => new ResourcePipelineContext());


        private string _globalPrefix = "";

        private Dictionary<string, string> _pathMap = new Dictionary<string, string>();
        
        protected override void DoInitialize(IResourceInitConfig initConfig)
        {
            _globalPrefix = (initConfig as AssetDBInitConfig).globalPrefix;
            string searchPath = _globalPrefix;
            
            if (searchPath.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
            {
                searchPath = searchPath.Substring(0, searchPath.Length - 1);
            }

            string[] findAssetIds = AssetDatabase.FindAssets("t:object", new[] {searchPath});
            for (int i = 0, l = findAssetIds.Length; i < l; ++i)
            {
                string path = AssetDatabase.GUIDToAssetPath(findAssetIds[i]);
                string ext = Path.GetExtension(path);
                string withoutSuffix = string.IsNullOrEmpty(ext) ? path : path.Replace(ext, "");
                _pathMap[withoutSuffix] = path;
            }
        }
        
        public override string GenerateLoadURL(string prefix, string localPath, string extension)
        {
            string key = _globalPrefix + prefix + localPath;
            string fullPath;
            if (_pathMap.TryGetValue(key, out fullPath))
            {
                return fullPath;
            }
            Debug.LogError("Can't find Asset: " + key);
            return key;
        }

        protected override ResourcePipelineContext CreatePipelineContext()
        {
            return _contextPool.Allocate();
        }

        protected override void DestroyPipelineContext(ResourcePipelineContext context)
        {
            _contextPool.Recycle(context);
        }

        protected override List<IResourceLoadPipe> CreateSyncLoadPipes(IResourceInitConfig initConfig)
        {
            return new List<IResourceLoadPipe>
                {
                    new AssetDBLoadAssetPipe()
                };
        }

        protected override List<IResourceLoadPipe> CreateAsyncLoadPipes(IResourceInitConfig initConfig)
        {
            return new List<IResourceLoadPipe>
                {
                    new AssetDBAsyncLoadAssetPipe()
                };
        }


        protected override bool ReleaseLoadItem(AbstractLoadItem item)
        {
            RemoveInstanceIdFromLoadItem(item);

            item.objRefCount = 0;
            item.instanceID = -1;
            bool needUnloadUnusedAsset = false;
            if (item.assetHandle != null)
            {
                needUnloadUnusedAsset = (item.assetHandle as AssetDBUAssetLoadHandle).Unload();
                item.assetHandle = null;
            }
            return needUnloadUnusedAsset;
        }


        protected override void UnloadAll()
        {
            var iter = this._loadItemMap.GetEnumerator();
            while (iter.MoveNext())
            {
                var item = iter.Current.Value;
                if (item.assetHandle != null)
                {
                    (item.assetHandle as AssetDBUAssetLoadHandle).Unload();
                    item.assetHandle = null;
                }
            }
            this._loadItemMap.Clear();
        }
    }
}
#endif
